//-----------------------------------------------------------------------
//  This file is part of the Microsoft Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
// 
//  THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//-----------------------------------------------------------------------

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Data.OleDb;
using System.Text;
using System.Windows.Forms;
using Microsoft.DataWarehouse.Interfaces;


namespace Microsoft.Samples.SqlServer.DataMining
{
    /// <summary>
    /// Summary description for PairwiseLinearRegressionViewer.
    /// </summary>
    public class PairwiseLinearRegressionViewer :
        System.Windows.Forms.UserControl,
        IMiningModelViewerControl
    {
        private string connectionString = string.Empty;
        private string miningModelName = string.Empty;
        private IServiceProvider serviceProvider;
        private System.Windows.Forms.RichTextBox richTextBox;

        private const int NODE_DISTRIBUTION = 16;
        private const int VALUE_TYPE = 5;
        private const int ATTRIBUTE_NAME = 0;
        private const int ATTRIBUTE_VALUE = 1;

        private const string TARGET_ATTRIBUTE = "1";
        private const string Y_INTERSECT = "3";
        private const string COEFFICIENT = "7";


        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public PairwiseLinearRegressionViewer()
        {
            // This call is required by the Windows.Forms Form
            // Designer.
            InitializeComponent();

            // Initialize variables
            connectionString = string.Empty;
            miningModelName = string.Empty;
        }

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code
        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PairwiseLinearRegressionViewer));
            this.richTextBox = new System.Windows.Forms.RichTextBox();
            this.SuspendLayout();
            // 
            // richTextBox
            // 
            resources.ApplyResources(this.richTextBox, "richTextBox");
            this.richTextBox.Name = "richTextBox";
            // 
            // PairwiseLinearRegressionViewer
            // 
            this.Controls.Add(this.richTextBox);
            this.MinimumSize = new System.Drawing.Size(416, 216);
            this.Name = "PairwiseLinearRegressionViewer";
            resources.ApplyResources(this, "$this");
            this.ResumeLayout(false);

        }
        #endregion

        static public string DisplayName
        {
            get
            {
                return "MyCompany_Pairwise_Linear_Regression_Viewer";
            }
        }

        public IServiceProvider ServiceProvider
        {
            get
            {
                return this.serviceProvider;
            }
            set
            {
                if (this.serviceProvider != value)
                    this.serviceProvider = value;
            }
        }

        public string ConnectionString
        {
            get
            {
                return this.connectionString;
            }
            set
            {
                if (this.connectionString != value)
                    this.connectionString = value;
            }
        }

        public string MiningModelName
        {
            get
            {
                return this.miningModelName;
            }
            set
            {
                if (this.miningModelName != value)
                    this.miningModelName = value;
            }
        }

        public bool LoadViewerData(object context)
        {
            StringBuilder textViewer = new StringBuilder();
            bool returnValue = true;

            // Open a new connection to the server.
            using (OleDbConnection connection = new OleDbConnection(this.connectionString))
            {
                connection.Open();

                // Create the OleDbCommand.
                string commandText = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                    "SELECT * FROM [{0}].CONTENT", this.MiningModelName);

                using (OleDbCommand command = new OleDbCommand())
                {
                    command.Connection = connection;
                    command.CommandText = commandText;

                    // Execute the command
                    using (OleDbDataReader dataReader = command.ExecuteReader())
                    {
                        // Add code to extract information from the schema here.
                        
                        // Extract information from the schema here - commented out
                        // Uncomment to add the schema column names to the output
                        #if ShowSchemaNames
                        DataTable schema = dataReader.GetSchemaTable();

                        int columnCount = schema.Columns.Count;
                        int rowCount = schema.Rows.Count;

                        for (int i = 0; i < rowCount; i++)
                        {
                            DataRow row = schema.Rows[i];
                            for (int j = 0; j < columnCount; j++)
                            {
                                // Add the column name
                                textViewer.AppendLine(row[j].ToString());
                            }
                        }

                        textViewer.AppendLine();
                        #endif

                        textViewer.AppendLine(MyCompanyPluginViewers.Properties.Resources.StrModelOutput);
                        textViewer.AppendLine();

                        // Enumerate the data
                        while (dataReader.Read())
                        {
                            try
                            {
                                for (int i = 0; i < dataReader.FieldCount; i++)
                                {
                                    if (i == NODE_DISTRIBUTION)
                                    {
                                        string formula = ExtractRegressionFormulaFromDist(
                                            (OleDbDataReader)dataReader.GetValue(i));

                                        // The first node generates an empty string.
                                        if (!String.IsNullOrEmpty(formula))
                                        {
                                            textViewer.AppendLine(formula);
                                        }
                                    }
                                }
                            }
                            catch (OleDbException e)
                            {
                                if (textViewer.Length > 0)
                                    textViewer.Remove(0, textViewer.Length);

                                textViewer.Append(e.Message);
                                returnValue = false;
                            }
                        }
                    }
                }

                // The connection is automatically closed when the
                // code exits the using block.
            }

            this.richTextBox.Text = textViewer.ToString();

            return returnValue;
        }

        public void ViewerActivated(bool isActivated)
        {

        }

        //------------------------------------------------
        // Helper functions
        //------------------------------------------------
        private static string ExtractRegressionFormulaFromDist(OleDbDataReader distReader)
        {
            string targetAttribute = string.Empty;
            StringBuilder regressionFormula = new StringBuilder();
            double val = 0.0;

            // Enumerate the data
            while (distReader.Read())
            {
                try
                {
                    // Get the value type
                    object dataValue = distReader.GetValue(VALUE_TYPE);
                    if (dataValue.ToString() == TARGET_ATTRIBUTE)
                    {
                        // Get the target attribute name
                        dataValue = distReader.GetValue(ATTRIBUTE_NAME);
                        targetAttribute = dataValue.ToString();

                        // The target attribute should always be first
                        System.Diagnostics.Debug.Assert(regressionFormula.Length == 0);

                        regressionFormula.AppendLine();
                        regressionFormula.Append(targetAttribute);
                        regressionFormula.Append(MyCompanyPluginViewers.Properties.Resources.EqualSign);
                    }
                    else if (dataValue.ToString() == Y_INTERSECT)
                    {
                        dataValue = distReader.GetValue(ATTRIBUTE_NAME);
                        string attName = dataValue.ToString();
                        if (attName == targetAttribute)
                        {
                            // This is the sample average of the attribute.
                            dataValue = distReader.GetValue(ATTRIBUTE_VALUE);
                            val = Convert.ToDouble(dataValue,
                                System.Globalization.CultureInfo.InvariantCulture);
                            regressionFormula.Append(val.ToString(
                                MyCompanyPluginViewers.Properties.Resources.FormatXXX,
                                System.Globalization.CultureInfo.InvariantCulture));
                        }
                        else
                        {
                            // Do nothing
                        }
                    }
                    else if (dataValue.ToString() == COEFFICIENT)
                    {
                        dataValue = distReader.GetValue(ATTRIBUTE_VALUE);
                        if (Convert.ToDouble(dataValue,
                            System.Globalization.CultureInfo.InvariantCulture) > 0)
                        {
                            regressionFormula.Append(MyCompanyPluginViewers.Properties.Resources.PlusSign);
                        }
                        else
                        {
                            regressionFormula.Append(MyCompanyPluginViewers.Properties.Resources.Space);
                        }

                        val = Convert.ToDouble(dataValue,
                            System.Globalization.CultureInfo.InvariantCulture);
                        regressionFormula.Append(val.ToString(MyCompanyPluginViewers.Properties.Resources.FormatXXX,
                            System.Globalization.CultureInfo.InvariantCulture));
                        regressionFormula.Append(MyCompanyPluginViewers.Properties.Resources.MultiplySign);
                        dataValue = distReader.GetValue(ATTRIBUTE_NAME);
                        regressionFormula.Append(dataValue.ToString());
                    }
                    else
                    {
                        // Do nothing
                    }
                }
                catch (OleDbException e)
                {
                    regressionFormula.AppendLine(string.Empty);
                    regressionFormula.AppendLine(e.Message);
                }
            }

            return regressionFormula.ToString().Trim();
        }
    }
}
